package com.ggh.websocket;
import com.ggh.entity.RoomBeanP;
import com.ggh.entity.TypeBean;
import com.ggh.entity.UserBean;
import com.ggh.handler.*;
import com.ggh.service.UserService;
import com.ggh.service.impl.UserServiceImpl;
import com.ggh.util.ApplicationContextProvider;
import com.ggh.util.JsonUtils;
import com.ggh.util.System_Mess;
import com.ggh.vo.UserToken;
import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.ApplicationContext;
import org.springframework.stereotype.Component;

import javax.websocket.*;
import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpoint;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
@Slf4j
@Component
@ServerEndpoint("/gamePKX/{userid}")
public class PK_WebSocket_P<E> {
	private static ReentrantLock lock = new ReentrantLock(true);
	/**
	 * 工具解析类
	 */
	private Gson gson= JsonUtils.get();
	/**
	 * 此处是解决无法注入的关键
	 */
	private static ApplicationContext applicationContext;
	/**
	 * @param applicationContext
	 */
	public static void setApplicationContext(ApplicationContext applicationContext) {
		PK_WebSocket_P.applicationContext = applicationContext;
	}
	private Session session;
	/**
	 * 用户类
	 */
	private UserBean user;
	/**
	 * 房间类
	 */
	private RoomBeanP room;
	private UserService us=ApplicationContextProvider.getBean(UserServiceImpl.class);
	/**
	 * 工具类
	 */
	private UserOperationP operp = new UserOperationP();
	/**
	 * map存储信息
	 */
	private Map<String, Object> map = new HashMap<String, Object>();
	/**
	 * 算法逻辑类
	 */
	private BeginToJudgePKPSiRen pkp = new BeginToJudgePKPSiRen();
	/**
	 * 用户操作类
	 */
	private EventHandler eventHandler = new EventHandler();
	/**
	 * @author : jj
	 * @date : 2019/10/5 10:48
	 * @description :打开链接
	 * @param userid
	 * @param session
	 * @return: void
	 * @throws
	 */
	@OnOpen
	public  void onOpen(@PathParam("userid") String userid, Session session)  {

		boolean bool = true;
		System.out.println("userid:"+userid);
		// 判断登陆
		if (userid != null) {
			// 获取用户信息
			this.user = us.selectByuserId(Integer.valueOf(userid));
			if (this.user != null) {
				// 将自己放入客户端集合
				Public_State_P.clients.put(String.valueOf(user.getUserid()), this);
				this.session = session;
				session.setMaxIdleTimeout(1800000);
				System_Mess.system_Mess.ToMessagePrint(user.getNickname() + "已连接");
				bool = false;
			}
		}
		if (bool) {
			try {
				if (this.session != null) {
					this.session.close();
				}
			} catch (IOException e) {
				System.out.println(e.getMessage());
			}
			System_Mess.system_Mess.ToMessagePrint("非法连接");
		}
		//startHeart();
	}

	/**
	 * 关闭
	 */
	@OnClose
	public void onClose() throws IOException {


			if (user != null) {// 人不为空
				user.getLock().lock();
				try {
					// 将自己放入客户端集合
					Public_State_P.clients.remove(String.valueOf(user.getUserid()));
					if (user.getReady_state() != -1) {
						if (room.getState()<1){
							if (room.getUserBean(user.getUserid()) != null) {
								room.getLock().lock();
								try {
									for (int i = 0; i < room.getUser_positions().length; i++) {
										if (room.getUser_positions()[i] == user.getUserid()) {
											room.getUser_positions()[i] = -1;
										}
									}
									room.getGame_userlist().remove(user);
								}catch (Exception e){
									System.out.println(e.getMessage());
								}finally {
									room.getLock().unlock();
								}
							}

						}
						user.setReady_state(2);
						user.setExit_state(1);
					}
					System_Mess.system_Mess.ToMessagePrint(user.getNickname() + "断开连接");
				}catch (Exception e){
					System.err.println(e.getMessage());
				}finally {
					user.getLock().unlock();
				}
			}



	}
	@OnError
	public void onError(Throwable t) throws Throwable {
		System.err.println(t.getMessage()+"错误日志！！！！");
		// 人不为空
		if (user != null) {
			System.out.println(user);
			// 将自己放入客户端集合
			Public_State_P.clients.remove(String.valueOf(user.getUserid()));
			if (user.getReady_state() != -1) {
				if (room.getState()<1){
					if (room.getUserBean(user.getUserid()) != null) {
						System.out.println(room);
						for (int i = 0; i < room.getUser_positions().length; i++) {
							if (room.getUser_positions()[i] == user.getUserid()) {
								room.getUser_positions()[i] = -1;
							}
						}
						room.getGame_userlist().remove(user);
					}
				}else {
					user.setReady_state(2);
					user.setExit_state(1);
				}

			}
		}
		t.printStackTrace();
		System.out.println("onError");
	}
	/**
	 * @author : jj
	 * @date : 2019/10/5 10:45
	 * @description :主程中心
	 * @param msg
	 * @param session
	 * @return: void
	 * @throws
	 */
	@OnMessage
	public void onMessage(String msg, Session session) {
		map.clear();// 清空map信息
		System_Mess.system_Mess.ToMessagePrint("接收到" + user.getNickname() + "的信息：" + msg);
		Map<String, String> jsonTo = gson.fromJson(msg, new TypeToken<Map<String, String>>() {
		}.getType());
		Lock lock = user.getLock();
		lock.lock();
		try {
			if ("HeartMessage".equals(jsonTo.get("type"))) {
				map.clear();
				// 心跳
				eventHandler.xtjc(user,map);
				sendMessageTo(map,user);
			}
			/* @description :百人牌九*/
			if (TypeBean.BaiRenPJ.equals(jsonTo.get("type"))) {
				map.clear();
				eventHandler.baiRenPJ(user,map);
				//发送消息给自己
				sendMessageTo(map, user);
			}
			/*@description :加入房间*/
			if (TypeBean.EnterRoom.equals(jsonTo.get("type"))&&user.getReady_state ()==-1) {
				map.clear();
				room = eventHandler.joinRoom(user, map, jsonTo.get("messages"));
				if (room == null) {
					sendMessageTo(map, user);
				} else {
					sendMessageTo(map, user);
					sendMessageToAll(map, room);
				}
			}
			/*@description :百人上庄规则*/
			if ("BaiRenShangZhuang".equals(jsonTo.get("type"))) {
				map.clear();
				eventHandler.szgz(user,map);
				sendMessageTo(map, user);
			}

			/* @description :百人用户上庄*/
			if ("BaiRenShangZhuangApply".equals(jsonTo.get("type"))) {
				map.clear();
				if (Integer.valueOf(jsonTo.get("messages"))>0){
					eventHandler.baiRenShangZhuang(user,map,Integer.valueOf(jsonTo.get("messages")));
					sendMessageTo(map, user);
				}


			}
			/*百人下庄*/
			if ("BaiRenXiaZhuangApply".equals(jsonTo.get("type")) && room.getState() == 1&&room.getTime()>0) {
				map.clear();
				eventHandler.baiRenXiaZhuangApply(user,map, jsonTo.get("messages"));
				sendMessageTo(map, user);
				sendMessageToAll(map, room);
			}
				/*下注 */
			if ("BaiRenMoneyBets".equals(jsonTo.get("type")) && room.getState() == 2 && room.getTime() > 0) {
				map.clear();
				eventHandler.baiRenXiaZhu(user,map, jsonTo.get("messages"));
				if (!map.get("type").equals("BaiRenMoneyBetsFailed")){
					sendMessageToAll(map, room);
				}
				sendMessageTo(map, user);
			}

			/** @description :扣牌动漫*/
			if ("BaiRenPJApply".equals(jsonTo.get("type")) && room.getState() == 4) {

				room.getLock().lock();
				try {
					room.setState(5);
					room.setTime(1);
				}catch (Exception e){
					System.out.println(e.getMessage());

				}finally {
					room.getLock().unlock();
				}
			}
			/**
			 * @description :提示组牌*/
			if ("BaiRenLargeZuPaiMessage".equals(jsonTo.get("type"))&&room.getState() ==6){
				map.clear();
				eventHandler.baiRenLargeZuPaiMessage(user,map);
				sendMessageTo(map, user);
			}
			/** @description :用户确认牌型*/
			if ("BaiRenLargeKouPaiMessage".equals(jsonTo.get("type"))&&room.getState() ==6){
				map.clear();
				eventHandler.baiRenLargeKouPaiMessage(user,map,jsonTo.get("messages"));
				sendMessageTo(map, user);
				sendMessageToAll(map, room);

			}
			/*用户退出*/
			if ("BaiRenLargeExit".equals(jsonTo.get("type"))){
				user.setExit_state(1);
				if (room.getState() ==0){
					if (room.getUpbanker().contains(user.getUserid())){
						int i = room.getUpbanker().indexOf(user.getUserid());
						room.getUpbanker().remove(i);
					}
				}
				map.put("type", "BaiRenLargeExitSuccess");
				map.put("messages", "");
				sendMessageTo(map, user);
				onClose();
			}
//-------------------------------------------------------------四人牌九---------------------------------------------------------------------------
			/* 四人牌九*/
			if (TypeBean.SiRenPJ.equals(jsonTo.get("type"))) {
				map.clear();
				eventHandler.siRenPj(user,map);
				sendMessageTo(map, user);
			}
			/* 获取房间列表*/
			if ("SiRenRoomInfo".equals(jsonTo.get("type"))) {
				map.clear();
				eventHandler.siRenRoomInfo(user,map, jsonTo.get("messages"));
				sendMessageTo(map, user);
			}
			/*加入房间*/
			if ("SiRenEnterRoom".equals(jsonTo.get("type"))&&user.getReady_state ()==-1) {
				map.clear();
				room = eventHandler.siRenEnterRoom(user, map, jsonTo.get("messages"));
				if (room!=null){
					sendMessageTo(map, user);
					map.put("type","SiRenEnterRoomAll");
					map.put("messages", gson.toJson(room));
					sendMessageToAll(map, room);
				}else {
					sendMessageTo(map, user);
				}
			}
			/*用户准备*/
			if ("SiRenPlayerReady".equals(jsonTo.get("type"))) {
				map.clear();
				boolean b = eventHandler.siRenPlayerReady(user, map);
				/*推送*/
				if (b){
					sendMessageTo(map, user);
					map.put("type","SiRenPlayerReadyAll");
					map.put("messages",user.getUserid());
					sendMessageToAll(map, room);
				}
				/*三人以上准备，开始游戏*/
				boolean gameStart = eventHandler.isGameStart(user, map, b);
				System.out.println(gameStart);
				if (gameStart){
					sendMessageTo(map,user);
					sendMessageToAll(map, room);
				}
			}
			// 用户取消准备
			if ("SiRenPlayerCanelReady".equals(jsonTo.get("type"))) {
				map.clear();
				if (user.getReady_state() == -1) {
				} else {
					int count = MatchingRoomP.getreadyUp(user, room);
					if (1 == count) {
						map.put("type", "SiRenPlayerCanelReadySuccess");
						map.put("messages", "取消准备！");
						map.put("stuts", 0);
						sendMessageTo(map, user);
						map.put("type","SiRenPlayerCanelReadyAll");
						map.put("messages", user.getUserid());
						sendMessageToAll(map, room);
					}
				}

			}
			// 用户抢庄
			if ("SiRenQiangZhuang".equals(jsonTo.get("type")) && room.getState() == 1) {
				map.clear();
				int messages = eventHandler.siRenQiangZhuang(user, map, jsonTo.get("messages"));
				if (messages==1){
					sendMessageToAll(map, room);
				}
				sendMessageTo(map, user);
			}

			/*用户下注*/
			if ("SiRenXiaZhu".equals(jsonTo.get("type")) && room.getState() == 4) {
				map.clear();
				eventHandler.siRenXiaZhu(user, map, jsonTo.get("messages"));
				sendMessageTo(map, user);
			}
			/*筛子结束*/
			if ("SiRenShaiZiAniEnd".equals(jsonTo.get("type")) && room.getState() == 13){
				user.setIdentify(2);
			}
			/*场景动漫*/
			if ("SiRenPjAniFinish".equals(jsonTo.get("type"))) {
				map.clear();
				user.setIdentify(1);
				map.put("type", TypeBean.SiRenGameInciDent);
				map.put("messages", gson.toJson(room));
				sendMessageTo(map, user);
			}
			/*四人小牌九2张金币结算*/
			if ("SiRenMoneyAniFinish".equals(jsonTo.get("type"))) {
				user.setSettlement(1);
			}

			/* 大牌九提示*/
			if ("SiRenLargeZuPaiMessage".equals(jsonTo.get("type"))) {
				map.clear();
				List<Integer> tips = pkp.tips(user.getBrands());
				map.put("type", TypeBean.SiRenLargeZuPaiMessageSUCCESS);
				map.put("messages", gson.toJson(tips));
				sendMessageTo(map, user);
			}

			// 用户组排
			if ("SiRenLargeKouPaiMessage".equals(jsonTo.get("type"))) {
				map.clear();
				// 进行排序，修改用户状态
				user.setPower_type(2);
				// 获取前端传输的牌的信息，替换牌
				String[] pai = jsonTo.get("messages").replace("[", "").replace("]", "").split(",");
				// 替换牌值
				if (pai.length>2){
					for (int i = 0; i < user.getBrands().size(); i++) {
						user.getBrands().set(i, Integer.valueOf(pai[i]));
					}
					// 重新判断
					user.setBrands(pkp.reordering(user.getBrands()));
					map.put("type", TypeBean.SiRenGameInciDent);
					map.put("messages", gson.toJson(room));
					sendMessageTo(map, user);
					map.put("type", "SiRenLargeKouPaiMessageAll");
					map.put("messages", user.getUserid());
					sendMessageToAll(map, room);

				}
			}

			// 用户退出
			if ("SiRenPlayerExit".equals(jsonTo.get("type"))) {
				map.clear();
				user.setReady_state(-1);
				operp.signOut(user,room);
				map.put("type", "SiRenPlayerExit");
				sendMessageTo(map, this.user);
				map.put("type","SiRenEnterRoomAll");
				map.put("messages", gson.toJson(room));
				sendMessageToAll(map, this.room);
				onClose();
			}
			// 聊天
			if ("chatX".equals(jsonTo.get("type"))) {
				map.clear();
				// 获取聊天信息
				String text = jsonTo.get("messages");
				System.out.println("text" + text);
				map.put("type", "chatX");
				//List list=new ArrayList();
				HashMap mapMessages =new HashMap();
				mapMessages.put("text",text);
				mapMessages.put("userid",user.getUserid());
				map.put("messages", gson.toJson(mapMessages));
				map.put("name",user.getNickname());
				sendMessageTo(map, this.user);
				sendMessageToAll(map, this.room);
			}
			// 观战人员
			if ("Watching".equals(jsonTo.get("type"))) {
				map.clear();
				List<UserBean> userlist = new ArrayList<>();
				for (UserBean ui:room.getGame_userlist()){
					if (ui.getUserid()==user.getUserid()||ui.getUserid()==room.getBanker()){
						continue;
					}
					UserBean uy=new UserBean();
					uy.setAvatarurl(ui.getAvatarurl());
					uy.setMoney(ui.getMoney());
					uy.setNickname(ui.getNickname());
					userlist.add(uy);
				}
				map.put("type","Watching");
				map.put("messages", gson.toJson(userlist));
				sendMessageTo(map, this.user);
			}
		}catch (Exception e){
			System.out.println(e.getMessage());
		}finally {
			lock.unlock();
		}

	}


	/**
	 * @author : jj
	 * @date : 2019/10/5 10:55
	 * @description :发送消息给除去自己以外的所有人
	 * @param returnMap
	 * @param rb
	 * @return: void
	 * @throws
	 */

	public synchronized void sendMessageToAll(Map<String, Object> returnMap, RoomBeanP rb) {

		for (UserBean userb : rb.getGame_userlist()) {
			PK_WebSocket_P webSocket = Public_State_P.clients.get(String.valueOf(userb.getUserid()));
			if (webSocket != null && webSocket.session.isOpen() && userb.getExit_state() == 0) {
				// 不等于自己的则发送消息
				if (userb.getUserid() != this.user.getUserid()) {
					returnMap.put("userid",userb.getUserid());
					webSocket.sendMessageTo(returnMap, userb);
				} else {
					continue;
				}
			} else {
				continue;
			}
		}
	}

	/**
	 * @description :给自己返回消息
	 * @param returnMap
	 * @param userBean
	 * @return: void
	 * @date : 2019/10/5 11:46
	 * @author : jj
	 * @throws
	 */
	public synchronized void sendMessageTo(Map<String, Object> returnMap, UserBean userBean) {

		if (this.session != null && this.session.isOpen() ) {
			returnMap.put("userid", userBean.getUserid());
			String returnjson = gson.toJson(returnMap);
			try {
				this.session.getBasicRemote().sendText(returnjson);
			} catch (IOException e) {
				e.printStackTrace();
			}
			//System_Mess.system_Mess.ToMessagePrint(userBean.getUserid() + "(自己)返回消息" + returnjson);
			log.info(userBean.getUserid() + "(自己)返回消息" + returnjson);
		}
	}
	/**
	 * @description :给自己返回消息
	 * @param userBean
	 * @return: void
	 * @date : 2019/10/5 11:46
	 * @author : jj
	 * @throws
	 */
	public synchronized void sendMessageAiTo(UserToken userToken, UserBean userBean) {

		if (this.session != null && this.session.isOpen() ) {
			String returnjson = gson.toJson(userToken);
			try {
				this.session.getBasicRemote().sendText(returnjson);
			} catch (IOException e) {
				e.printStackTrace();
			}
			System_Mess.system_Mess.ToMessagePrint(userBean.getUserid() + "(自己)返回消息" + returnjson);
		}
	}

	public UserBean getUser() {
		return user;
	}

	public void setUser(UserBean user) {
		this.user = user;
	}


	public Session getSession() {
		return session;
	}

	public void setSession(Session session) {
		this.session = session;
	}


}